#include "../include/command.h"
#include <ctype.h>

/**
 * 命令分发主入口
 * @param cmd_str 命令字符串
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_dispatch(const char* cmd_str, char* response, size_t resp_size, Cache* cache)
{
    // 参数检测，如果参数为空，则返回失败
    if(!cmd_str || !response || resp_size <= 0 || !cache)
    {
        snprintf(response, resp_size, "ERR invalid argument");
        return -1;
    }

    // 字符串预处理，去除前导空格
    char* cmd = strdup(cmd_str);
    if(!cmd)
    {
        snprintf(response, resp_size, "ERR memory");
        return -1;
    }

    // 解析命令
    // 分割参数
    char* argv[8];
    int argc = 0;
    // strtok 函数会修改原字符串,将字符串分割成多个子字符串，返回分割后的第一个子字符串的指针
    // 第一次调用时，cmd_str 作为参数，后续调用时，cmd_str 作为 NULL
    char* token = strtok(cmd, " \t\r\n");
    while(token && argc < 8)
    {
        argv[argc++] = token;
        token = strtok(NULL, " \t\r\n");
    }
    
    if(argc == 0)
    {
        snprintf(response, resp_size, "ERR empty command");
        free(cmd);
        return -1;
    }
    
    // 将命令转换为小写
    for(char* p = argv[0]; *p != '\0'; p++)
    {
        *p = tolower(*p);
    }
    
    // 根据命令类型调用不同的处理函数
    int ret = -1;
    if(strcmp(argv[0], "set") == 0)
    {
        ret = command_set(argv, argc, response, resp_size, cache);
    }
    else if(strcmp(argv[0], "get") == 0)
    {
        ret = command_get(argv, argc, response, resp_size, cache);
    }
    else if(strcmp(argv[0], "del") == 0)
    {
        ret = command_del(argv, argc, response, resp_size, cache);
    }
    else if(strcmp(argv[0], "expire") == 0)
    {
        ret = command_expire(argv, argc, response, resp_size, cache);
    }
    else if(strcmp(argv[0], "ttl") == 0)
    {
        ret = command_ttl(argv, argc, response, resp_size, cache);
    }
    else {
        snprintf(response, resp_size, "ERR unknown command");
        ret = -1;
    }
    free(cmd);
    return ret;
}

/**
 * SET 命令
 * @param argv 命令参数
 * @param argc 命令参数个数
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_set(char** argv, int argc, char* response, size_t resp_size, Cache* cache)
{
    if(argc < 3)
    {
        snprintf(response, resp_size, "ERR wrong number of arguments for 'set' command");
        return -1;
    }

    const char* key = argv[1];
    const char* value = argv[2];
    int ttl = 0;
    // 如果参数个数大于3，说明设置了ttl
    if(argc > 3)
    {
        ttl = atoi(argv[3]);
    }

    // 设置缓存
    if(cache_set(cache, key, value, ttl) == 0)
    {
        snprintf(response, resp_size, "OK");
        return 0;
    }
    else
    {
        snprintf(response, resp_size, "ERR memory allocation failed");
        return -1;
    }
}

/**
 * GET 命令
 * @param argv 命令参数
 * @param argc 命令参数个数
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_get(char** argv, int argc, char* response, size_t resp_size, Cache* cache)
{
    if(argc < 2)
    {
        snprintf(response, resp_size, "ERR wrong number of arguments for 'get' command");
        return -1;
    }

    const char* key = argv[1];
    CacheNode* node = cache_get(cache, key);
    if(node && node->value)
    {
        snprintf(response, resp_size, "%s", node->value);
        return 0;
    }
    else
    {
        snprintf(response, resp_size, "ERR key not found");
        return -1;
    }
}

/**
 * DEL 命令
 * @param argv 命令参数
 * @param argc 命令参数个数
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_del(char** argv, int argc, char* response, size_t resp_size, Cache* cache)
{
    if(argc < 2)
    {
        snprintf(response, resp_size, "ERR wrong number of arguments for 'del' command");
        return -1;
    }

    const char* key = argv[1];
    if(cache_delete(cache, key) == 0)
    {
        snprintf(response, resp_size, "DEL %s OK", key);
        return 0;
    }
    else
    {
        snprintf(response, resp_size, "ERR key not found");
        return -1;
    }
}

/**
 * EXPIRE 命令
 * @param argv 命令参数
 * @param argc 命令参数个数
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_expire(char** argv, int argc, char* response, size_t resp_size, Cache* cache)
{
    if(argc < 3)
    {
        snprintf(response, resp_size, "ERR wrong number of arguments for 'expire' command");
        return -1;
    }

    const char* key = argv[1];
    int ttl = atoi(argv[2]);
    if(cache_expire(cache, key, ttl) == 0)
    {
        snprintf(response, resp_size, "EXPIRE %s %d OK", key, ttl);
        return 0;
    }
    else
    {
        snprintf(response, resp_size, "ERR key not found");
        return -1;
    }
}

/**
 * TTL 命令
 * @param argv 命令参数
 * @param argc 命令参数个数
 * @param response 输出缓冲区
 * @param resp_size 输出缓冲区大小
 * @param cache 缓存指针
 * @return 0成功，-1失败
 */
int command_ttl(char** argv, int argc, char* response, size_t resp_size, Cache* cache)
{
    if(argc < 2)
    {
        snprintf(response, resp_size, "ERR wrong number of arguments for 'ttl' command");
        return -1;
    }

    const char* key = argv[1];
    int ttl = cache_ttl(cache, key);
    if(ttl == -1)
    {
        snprintf(response, resp_size, "Never Expires");
        return 0;
    }
    else if(ttl == -2)
    {
        snprintf(response, resp_size, "ERR key not found");
        return -1;
    }
    else
    {
        snprintf(response, resp_size, "TTL %s %d", key, ttl);
        return 0;
    }
}
